package com.mallify.service.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.mallify.common.model.order.StoreOrder;
import com.mallify.common.request.PageParamRequest;
import com.mallify.common.utils.DateUtil;
import com.mallify.common.utils.vo.DateLimitUtilVo;
import com.mallify.service.mapper.StoreOrderMapper;
import com.mallify.service.service.StoreOrderService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;

/**
 * StoreOrderServiceImpl 接口实现
 * +----------------------------------------------------------------------
 * | HANSON [ HANSON赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 * | Licensed HANSON并不是自由软件，未经许可不能去掉HANSON相关版权
 * +----------------------------------------------------------------------
 * | Author: HANSON Team <hanson0622@126.com>
 * +----------------------------------------------------------------------
 */
@Service
public class StoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper, StoreOrder> implements StoreOrderService {

    @Resource
    private StoreOrderMapper storeOrderMapper;

    /**
     * 通过日期获取订单数量
     *
     * @param date 日期，yyyy-MM-dd格式
     * @return Integer
     */
    @Override
    public Integer getOrderNumByDate(String date) {
        QueryWrapper<StoreOrder> wrapper = new QueryWrapper<>();
        wrapper.select("id");
        wrapper.eq("paid", 1);
        wrapper.apply("date_format(create_time, '%Y-%m-%d') = {0}", date);
        return storeOrderMapper.selectCount(wrapper);
    }

    /**
     * 通过日期获取支付订单金额
     *
     * @param date 日期，yyyy-MM-dd格式
     * @return BigDecimal
     */
    @Override
    public BigDecimal getPayOrderAmountByDate(String date) {
        QueryWrapper<StoreOrder> wrapper = new QueryWrapper<>();
        wrapper.select("IFNULL(SUM(pay_price), 0) as pay_price");
        wrapper.eq("paid", 1);
        //灵活性：apply 允许你直接编写原生 SQL 片段，适用于复杂的查询条件。
        //安全性：通过占位符 {0} 和参数的方式，可以防止 SQL 注入。
        //动态性：可以根据传入的参数动态生成 SQL 条件。
        wrapper.apply("date_format(create_time, '%Y-%m-%d') = {0}", date);
        StoreOrder storeOrder = storeOrderMapper.selectOne(wrapper);
        return storeOrder.getPayPrice();
    }

    /**
     * 通过时间段获取支付订单金额
     *
     * @param startDate 日期
     * @param endDate   日期
     * @return BigDecimal
     */
    @Override
    public BigDecimal getPayOrderAmountByPeriod(String startDate, String endDate) {
        QueryWrapper<StoreOrder> wrapper = new QueryWrapper<>();
        wrapper.select("IFNULL(SUM(pay_price), 0) as pay_price");
        wrapper.eq("paid", 1);
        //灵活性：apply 允许你直接编写原生 SQL 片段，适用于复杂的查询条件。
        //安全性：通过占位符 {0} 和参数的方式，可以防止 SQL 注入。
        //动态性：可以根据传入的参数动态生成 SQL 条件。
        wrapper.apply("date_format(create_time, '%Y-%m-%d') between {0} and {1}", startDate, endDate);
        StoreOrder storeOrder = storeOrderMapper.selectOne(wrapper);
        return storeOrder.getPayPrice();
    }

    /**
     * 按开始结束时间分组订单
     *
     * @param date    String 时间范围
     * @param lefTime int 截取创建时间长度
     * @return HashMap<String, Object>
     * @author hanson.huang
     * @since 2025-02-9
     */
    @Override
    public List<StoreOrder> getOrderGroupByDate(String date, int lefTime) {
        QueryWrapper<StoreOrder> queryWrapper = new QueryWrapper<>();
        // "left(create_time, " + lefTime + ")  left函数是返回日期的前几位，yyyy-MM-dd HH:mm:ss  lefTime为7时，返回yyyy-MM  lefTime为10时，返回yyyy-MM-dd
        queryWrapper.select("sum(pay_price) as pay_price", "left(create_time, " + lefTime + ") as orderId", "count(id) as id");
        if (StringUtils.isNotBlank(date)) {
            DateLimitUtilVo dateLimit = DateUtil.getDateLimit(date);
            queryWrapper.between("create_time", dateLimit.getStartTime(), dateLimit.getEndTime());
        }
        queryWrapper.groupBy("orderId").orderByAsc("orderId");
        return storeOrderMapper.selectList(queryWrapper);
    }

    /**
     * @param userId           用户uid
     * @param pageParamRequest 分页参数
     * @return List
     */
    @Override
    public List<StoreOrder> findPaidListByUid(Integer userId, PageParamRequest pageParamRequest) {
        PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        LambdaQueryWrapper<StoreOrder> lqw = new LambdaQueryWrapper<>();
        lqw.eq(StoreOrder::getUid, userId);
        lqw.eq(StoreOrder::getPaid, true);
        lqw.eq(StoreOrder::getIsDel, false);
        lqw.lt(StoreOrder::getRefundStatus, 2);
        lqw.orderByDesc(StoreOrder::getId);
        return storeOrderMapper.selectList(lqw);
    }

    /**
     * 获取用户消费金额(时间)
     *
     * @param userId 用户uid
     * @return BigDecimal
     */
    @Override
    public BigDecimal getSumPayPriceByUidAndDate(Integer userId, String date) {
        LambdaQueryWrapper<StoreOrder> lqw = new LambdaQueryWrapper<>();
        lqw.select(StoreOrder::getPayPrice);
        lqw.eq(StoreOrder::getPaid, true);
        lqw.eq(StoreOrder::getIsDel, false);
        lqw.eq(StoreOrder::getUid, userId);
        lqw.lt(StoreOrder::getRefundStatus, 2);
        if (StringUtils.isNotBlank(date)) {
            DateLimitUtilVo dateLimit = DateUtil.getDateLimit(date);
            lqw.between(StoreOrder::getCreateTime, dateLimit.getStartTime(), dateLimit.getEndTime());
        }
        List<StoreOrder> orderList = storeOrderMapper.selectList(lqw);
        return orderList.stream().map(StoreOrder::getPayPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 获取用户总消费金额
     * @param userId 用户uid
     * @return BigDecimal
     */
    @Override
    public BigDecimal getSumPayPriceByUid(Integer userId) {
        LambdaQueryWrapper<StoreOrder> lqw = new LambdaQueryWrapper<>();
        lqw.select(StoreOrder::getPayPrice);
        lqw.eq(StoreOrder::getPaid, true);
        lqw.eq(StoreOrder::getIsDel, false);
        lqw.eq(StoreOrder::getUid, userId);
        lqw.lt(StoreOrder::getRefundStatus, 2);
        List<StoreOrder> orderList = storeOrderMapper.selectList(lqw);
        return orderList.stream().map(StoreOrder::getPayPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 获取订单数量(时间)
     * @param uid 用户uid
     * @return Integer
     */
    @Override
    public Integer getOrderCountByUidAndDate(Integer uid, String date) {
        LambdaQueryWrapper<StoreOrder> lqw = new LambdaQueryWrapper<>();
        lqw.eq(StoreOrder::getPaid, true);
        lqw.eq(StoreOrder::getIsDel, false);
        lqw.eq(StoreOrder::getUid, uid);
        lqw.lt(StoreOrder::getRefundStatus, 2);
        if (StringUtils.isNotBlank(date)) {
            DateLimitUtilVo dateLimit = DateUtil.getDateLimit(date);
            lqw.between(StoreOrder::getCreateTime, dateLimit.getStartTime(), dateLimit.getEndTime());
        }
        return storeOrderMapper.selectCount(lqw);
    }

    /**
     * 获取订单总数量
     * @param uid 用户uid
     * @return Integer
     */
    @Override
    public Integer getOrderCountByUid(Integer uid) {
        LambdaQueryWrapper<StoreOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(StoreOrder::getPaid, true);
        lqw.eq(StoreOrder::getIsDel, false);
        lqw.eq(StoreOrder::getUid, uid);
        lqw.lt(StoreOrder::getRefundStatus, 2);
        return storeOrderMapper.selectCount(lqw);
    }
}
